package com.kecheng.servermonitor.controller;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.kecheng.servermonitor.config.cache.HeartbeatCache;
import com.kecheng.servermonitor.entity.ServiceStatus;
import com.kecheng.servermonitor.entity.StatusReportRequest;
import com.kecheng.servermonitor.entity.TaskProperties;
import com.kecheng.servermonitor.service.MailService;
import com.kecheng.servermonitor.util.SystemMonitorUtil;
import lombok.val;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api")
public class ServiceStatusController {
    @Resource
    private MailService mailService;
    @Resource
    private TaskProperties taskProperties;
    @Resource
    private HeartbeatCache heartbeatCache;
    @Value("${count}")
    private int count;

    // 缓存用于记录每个clientId的发送次数,防止一直发送邮件，60分钟后刷新缓存，如果还有就再次发送报警
    private final Cache<String, Integer> heartbeatNotificationCache = Caffeine.newBuilder()
            .expireAfterWrite(60, TimeUnit.MINUTES) // 缓存项60分钟后过期
            .build();


    @PostMapping("/report-status")
    public String receiveStatus(@RequestBody StatusReportRequest requestBody,
                                @RequestHeader("email") String email,
                                @RequestHeader("client-id") String rawClientId) {

        // 1. 解码 client-id
        String clientId = decodeClientId(rawClientId);

        // 2. 如果当前配置为客户端，直接退出（保护性判断）
        if (taskProperties.isClient()) {
            System.out.println("当前配置为客户端，请切换至服务端");
            return "error";
        }

        // 3. 更新心跳时间
        heartbeatCache.updateHeartbeat(clientId, email);

        // 4. 输出收到心跳的基本信息
        System.out.println("收到来自客户端【" + clientId + "】的心跳：" + requestBody.getServiceStatuses());

        // 5. 打印每个服务状态
        printServiceStatus(requestBody.getServiceStatuses());

        // 6. 检查并触发告警
        handleAbnormalServices(clientId, email, requestBody);

        return "OK";
    }

// --------------------- 辅助方法区 ---------------------

    /** 解码 clientId */
    private String decodeClientId(String clientId) {
        try {
            return URLDecoder.decode(clientId, StandardCharsets.UTF_8.name());
        } catch (Exception e) {
            System.out.println("client-id 解码失败，仍使用原始值: " + clientId);
            return clientId;
        }
    }

    /** 打印每个服务的状态 */
    private void printServiceStatus(List<ServiceStatus> statusList) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String now = LocalDateTime.now().format(formatter);
        for (ServiceStatus status : statusList) {
            System.out.println(now + " 接收到服务状态：" + status.getServiceName()
                    + " - " + (status.isHealthy() ? "正常" : "离线"));
        }
    }

    /** 处理异常服务告警 */
    private void handleAbnormalServices(String clientId, String email, StatusReportRequest req) {
        List<ServiceStatus> abnormal = req.getServiceStatuses().stream()
                .filter(s -> !s.isHealthy())
                .collect(Collectors.toList());

        if (abnormal.isEmpty()) {
            return;
        }

        // 拼装邮件内容
        String subject = "【" + clientId + "系统告警】监测到服务异常";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String currentTime = LocalDateTime.now().format(formatter);

        StringBuilder body = new StringBuilder();
        body.append("智慧实验室系统以下服务状态发生异常：\n\n")
                .append("当前监测时间：").append(currentTime).append("\n");

        for (ServiceStatus s : abnormal) {
            body.append("服务名：").append(s.getServiceName())
                    .append("，状态：").append("离线").append("\n");
        }

        body.append(SystemMonitorUtil.generateSystemReport(req.getMemoryUsage(), req.getCpuUsage(), req.getDiskUsage()));

        // 读取本客户端的告警次数
        Integer currentCount = heartbeatNotificationCache.get(clientId + ":service-alert-count", k -> 1);

        if (currentCount <= count) {
            mailService.sendAlertMail(Arrays.asList(email.split(",")), subject, body.toString(), currentCount, clientId);
            heartbeatNotificationCache.put(clientId + ":service-alert-count", currentCount + 1);
        } else {
            System.out.println(clientId + " 服务监测已发送 " + count + " 次报警邮件，达到上限");
        }
    }


}
